package com.sbwebsocket.core.redis;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sbwebsocket.core.model.bo.DirectMessageBody;
import com.sbwebsocket.core.model.contants.LogPrefix;
import com.sbwebsocket.core.model.contants.SendStatus;
import com.sbwebsocket.core.redis.model.contants.WsMessageRedisKeyPrefix;
import com.sbwebsocket.core.service.MessageDeliveryListener;
import com.sbwebsocket.core.service.MessageQueue;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Auther: GSJ
 * @Date: 2022/2/10
 * @Description:
 * @version: 1.0
 */
@Slf4j
public class RedisDirectMessageQueue implements MessageQueue<DirectMessageBody> {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private RedisModeUtil redisModeUtil;
    
    @Autowired
    private MessageDeliveryListener messageDeliveryListener;
    
    @Override
    public boolean delivery(DirectMessageBody messageBody) {

        //1.根据clientkey取到对应的serverkey(订阅的key),把消息推入其中
        List<String> sendClientIdentitys = messageBody.getSendClientIdentitys();
        if (CollUtil.isEmpty(sendClientIdentitys)) {
            log.warn(LogPrefix.DIRECT + "sendClientIdentitys不能为空!");
            return false;
        }

        //把客户端相同的服务归类
        Map<String, List<String>> servers = new HashMap<>();
        for (String clientIdentity : sendClientIdentitys) {
            String serverKey = redisModeUtil.getServerKey(clientIdentity);
            if(StrUtil.isBlank(serverKey)) {
                messageDeliveryListener.handle(SendStatus.OFF_LINE,clientIdentity,messageBody.getBody());
                continue;
            }
            List<String> clients = servers.get(serverKey);
            if (null == clients) {
                clients = new ArrayList<>();
                servers.put(serverKey, clients);
            }
            clients.add(clientIdentity);
        }

        if(CollUtil.isEmpty(servers)) return false;
        //往对应的服务器的主题发送消息
        for (String serverKey : servers.keySet()) {
            List<String> clientIdentitys = servers.get(serverKey);
            try {
                DirectMessageBody batch = new DirectMessageBody(clientIdentitys,messageBody.getBody());
                redisTemplate.convertAndSend(WsMessageRedisKeyPrefix.SERVER_MSG_DIRECT + serverKey,
                        objectMapper.writeValueAsString(batch));
            } catch (Exception e) {
                //todo: 可考虑延迟重试(可能redis,异常掉线，或网线问题导致)
                messageDeliveryListener.handle(SendStatus.FAIL,clientIdentitys,messageBody.getBody());
                log.error("direct-msg-redis->delivery投递失败！",e);
            }
        }

        return true;
    }



}
